package com.suke.czx.modules.sys.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.suke.czx.common.annotation.SysLog;
import com.suke.czx.common.base.AbstractController;
import com.suke.czx.common.exception.RRException;
import com.suke.czx.common.utils.Constant;
import com.suke.czx.common.utils.Constant.MenuType;
import com.suke.czx.common.utils.FieldConstant;
import com.suke.czx.common.utils.ListUtil;
import com.suke.czx.common.utils.R;
import com.suke.czx.common.validate.SysMenuSaveGroup;
import com.suke.czx.common.validate.SysMenuUpdateGroup;
import com.suke.czx.modules.sys.entity.SysMenu;
import com.suke.czx.modules.sys.service.SysMenuService;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 应用模块名称: 资源
 * 代码描述: 资源控制层
 * copyright: AUZAR ALL RIGHTS RESERVED
 * company: AUZAR
 *
 * @author: 颜米晨
 * @date: 2021/08/27 16:31
 */
@Validated
@RestController
@RequestMapping("/api/menu")
@AllArgsConstructor
@Api(value = "SysMenuController", tags = "系统资源")
public class SysMenuController extends AbstractController {

	private final SysMenuService sysMenuService;

	/**
	 * 分页查询资源列表
	 * @return VO
	 */
	@RequestMapping(value = "/list", method = RequestMethod.POST)
	@PreAuthorize("hasRole('but:menu:list')")
	public R list(@RequestParam Map<String, Object> params) {
		if (StrUtil.isBlankIfStr(params.get(FieldConstant.PAGE)) || StrUtil.isBlankIfStr(FieldConstant.LIMIT)) {
			return R.error("缺少分页信息");
		}
		//查询列表数据
		QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
		if (params.size() > 2) {
			queryWrapper.like(!StrUtil.isBlankIfStr(params.get(FieldConstant.NAME)), StrUtil.toUnderlineCase(FieldConstant.NAME), params.get(FieldConstant.NAME));
		}
		IPage<SysMenu> sysMenuPage = sysMenuService.page(mpPageConvert.pageParamConvert(params), queryWrapper);
		return Objects.requireNonNull(R.ok().put(FieldConstant.TOTAL, sysMenuPage.getTotal())).setData(Optional.ofNullable(sysMenuPage.getRecords()).orElse(Lists.newArrayList()));
	}

	/**
	 * 资源详情
	 * @param menuId 资源id
	 * @return VO
	 */
	@RequestMapping(value = "/info/{menuId}", method = RequestMethod.GET)
	@PreAuthorize("hasRole('but:menu:info')")
	public R info(@PathVariable("menuId") Long menuId){
		SysMenu menu = sysMenuService.getById(menuId);
		// 获取父资源
		if (menu.getParentId() != null && menu.getParentId() > 0) {
			menu.setParentName(sysMenuService.getById(menu.getParentId()).getName());
		}
		// 获取子资源数据集
		menu.setList(sysMenuService.list(new QueryWrapper<SysMenu>().eq(StrUtil.toUnderlineCase(FieldConstant.PARENT_ID), menu.getMenuId()))
				.stream().map(m -> m.getMenuId() + Constant.COLON + m.getName()).collect(Collectors.toList()));
		return R.ok().setData(menu);
	}

	/**
	 * 查询所有资源
	 * @return VO
	 */
	@RequestMapping(value = "/select", method = RequestMethod.POST)
	@PreAuthorize("hasRole('but:menu:select')")
	public R select() {
		// 查询列表数据
		QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
		queryWrapper.ne(StrUtil.toUnderlineCase(FieldConstant.MENU_ID), Constant.PROJECT_CONTROL_MENU);
		List<SysMenu> parentMenuList = sysMenuService.list(queryWrapper);
		return R.ok().setData(parentMenuList);
	}

	/**
	 * 保存资源(仅可保存自身及其父资源)
	 * @param menu 资源
	 * @return VO
	 */
	@SysLog("保存资源")
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	@PreAuthorize("hasRole('but:menu:save')")
	public R save(@Validated(SysMenuSaveGroup.class) SysMenu menu){
		// 数据校验
		verifyForm(menu);
		sysMenuService.save(menu);
		return R.ok();
	}

	/**
	 * 更新资源(仅可更新自身及其父资源)
	 * @param menu 资源
	 * @return VO
	 */
	@SysLog("更新资源")
	@RequestMapping(value = "/update",method = RequestMethod.POST)
	@PreAuthorize("hasRole('but:menu:update')")
	public R update(@Validated(SysMenuUpdateGroup.class) SysMenu menu) {
		// 数据校验
		verifyForm(menu);
		sysMenuService.updateById(menu);
		return R.ok();
	}

	/**
	 * 删除资源
	 * @param menuId 资源id
	 * @return VO
	 */
	@SysLog("删除资源")
	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	@PreAuthorize("hasRole('but:menu:delete')")
	public R delete(@NotNull(message = "资源编码不能为空") Long menuId) {
		// 判断是否有子资源
		List<SysMenu> menuList = sysMenuService.list(new QueryWrapper<SysMenu>().eq(StrUtil.toUnderlineCase(FieldConstant.PARENT_ID), menuId));
		if (ListUtil.size(menuList) > 0) {
			return R.error("请先删除子菜单或按钮");
		}
		sysMenuService.removeById(menuId);
		return R.ok();
	}

	/**
	 * 验证资源参数是否正确
	 * @param menu 资源对象
	 */
	private void verifyForm(SysMenu menu) {
		if (StrUtil.isBlank(menu.getName())) {
			throw new RRException("资源名称不能为空");
		}
		if (menu.getParentId() == null) {
			throw new RRException("上级资源不能为空");
		}
//		if (menu.getType() == MenuType.MENU.getValue()) {
//			if (StrUtil.isBlank(menu.getUrl())) {
//				throw new RRException("菜单URL不能为空");
//			}
//		}
		// 上级菜单类型
		int parentType = MenuType.CATALOG.getValue();
		if (menu.getParentId() != 0) {
			SysMenu parentMenu = sysMenuService.getById(menu.getParentId());
			parentType = parentMenu.getType();
		}
		// 目录、菜单
		if (menu.getType() == MenuType.CATALOG.getValue() ||
				menu.getType() == MenuType.MENU.getValue()) {
			if (parentType != MenuType.CATALOG.getValue()) {
				throw new RRException("上级资源只能为目录类型");
			}
			return;
		}
		// 按钮
		if (menu.getType() == MenuType.BUTTON.getValue()) {
			if (parentType != MenuType.MENU.getValue()) {
				throw new RRException("上级资源只能为菜单类型");
			}
		}
	}

}
